#pragma once
#include "brpc/server.h"
#include "butil/logging.h"

#include "asr.hpp"     //语音识别
#include "speech.pb.h" //protobuf
#include "logger.hpp"  //日志
#include "etcd.hpp"    //服务注册
#include <memory>

class SpeechServiceImpl : public lch_im::SpeechService
{
public:
    SpeechServiceImpl(const ASRClient::ptr &asr_client) : _asr_client(asr_client) {}
    ~SpeechServiceImpl() {}
    void SpeechRecognition(::google::protobuf::RpcController *controller,
                           const ::lch_im::SpeechRecognitionReq *request,
                           ::lch_im::SpeechRecognitionRsp *response,
                           ::google::protobuf::Closure *done)
    {
        LOG_DEBUG("收到语音转文字请求！");
        brpc::ClosureGuard rpc_guard(done);
        // 1. 取出请求中的语音数据
        // 2. 调用语音sdk模块进行语音识别，得到响应
        std::string err;
        std::string res = _asr_client->recognize(request->speech_content(), err);
        if (res.empty())
        {
            LOG_ERROR("{} 语音识别失败！", request->request_id());
            response->set_request_id(request->request_id());
            response->set_success(false);
            response->set_errmsg("语音识别失败:" + err);
            return;
        }
        // 3. 组织响应
        response->set_request_id(request->request_id());
        response->set_success(true);
        response->set_recognition_result(res);
    }

private:
    ASRClient::ptr _asr_client;
};

class SpeechServer
{
public:
    using ptr = std::shared_ptr<SpeechServer>;

    SpeechServer(const ASRClient::ptr &asr_client, const Registery::ptr &reg_client, const std::shared_ptr<brpc::Server> &rpc_server)
        : _asr_client(asr_client),
          _reg_client(reg_client),
          _rpc_server(rpc_server)
    {
    }

    ~SpeechServer() {}

    void start()
    {
        _rpc_server->RunUntilAskedToQuit();
    }

private:
    ASRClient::ptr _asr_client;
    Registery::ptr _reg_client;
    std::shared_ptr<brpc::Server> _rpc_server;
};

class SpeechServerBuild
{
public:
    void create_asr_object(const std::string &app_id, const std::string &api_key, const std::string &secret_key)
    {
        _asr_client = std::make_shared<ASRClient>(app_id, api_key, secret_key);
    }

    void create_reg_object(const std::string &reg_host, const std::string &service_name, const std::string &access_host)
    {
        _reg_client = std::make_shared<Registery>(reg_host);
        _reg_client->registry(service_name, access_host);
    }

    void create_rpc_object(uint16_t port, int32_t timeout, uint8_t num_threads)
    {
        // 语音识别功能必须在rpc之前
        if (!_asr_client)
        {
            LOG_ERROR("还未初始化语音服务");
            abort();
        }

        _rpc_server = std::make_shared<brpc::Server>();
        SpeechServiceImpl *speech_service = new SpeechServiceImpl(_asr_client);
        bool ret = _rpc_server->AddService(speech_service,
                                           brpc::ServiceOwnership::SERVER_OWNS_SERVICE);

        if (ret == -1)
        {
            LOG_ERROR("添加rpc服务失败");
            abort();
        }
        // 启动服务器
        brpc::ServerOptions options;
        // 连接空闲超时时间，-1表示
        options.idle_timeout_sec = -1;
        // io线程数量
        options.num_threads = 1;
        ret = _rpc_server->Start(port, &options);
        if (ret == -1)
        {
            LOG_ERROR("服务启动失败");
            abort();
        }
    }

    SpeechServer::ptr build()
    {
        if (!_asr_client)
        {
            LOG_ERROR("没有初始化语音服务");
            abort();
        }

        if (!_reg_client)
        {
            LOG_ERROR("没有初始化服务注册服务");
            abort();
        }

        if (!_rpc_server)
        {
            LOG_ERROR("没有初始化rpc服务");
            abort();
        }

        SpeechServer::ptr server = std::make_shared<SpeechServer>(_asr_client, _reg_client, _rpc_server);
        return server;
    }

private:
    ASRClient::ptr _asr_client;
    Registery::ptr _reg_client;
    std::shared_ptr<brpc::Server> _rpc_server;
};